// miniprogram/pages/playGame/playGame.js
const app = getApp()
var watcher = null
var countdownTimer = null

Page({
  data: {
    room: "", // 房间id
    openid: "",
    role: "",
    solve: false,
    scenesCardArray: [],
    tempScenesCardArray: [],
    operation: "none", // 当前操作
    hintText: "",
    tempHintText: "",
    buttonLeft: "换牌",
    buttonRight: "选择",
    changeCardIndex: -1, // 换牌时选中的卡片index
    changeCardTimes: 4,  // 当前剩余回合数
    userArray: [],
    countdown: 180,
    showSheet: false, // 凶手按钮
    trickCardId: "",
    clueCardId: "",
    showSolveSheet: false, // 破案按钮
    solveUserArray: [],
    resetCommand: true,
    refreshTime: 0,
    height: "320rpx",
  },
  
  onShow: function () {
    // 设置图片宽高比 11:17
    var that = this
    var gridGap = 10 / 750 * wx.getSystemInfoSync().windowWidth
    setTimeout(function() {
      var query = wx.createSelectorQuery()
      query.select("#container").boundingClientRect(function (rect) {
        if (rect == null) return
        that.setData({
          height: (rect.width / 4 - gridGap) / 11 * 17 + "px"
        })
      }).exec()
    }, 800)
  },

  onLoad: function (options) {
    this.init(options.room, "房间" + options.room)
  },

  onUnload: function () {
    this.detach()
  },

  onRefresh: function() {
    if (Date.now() - this.data.refreshTime < 8000) {
      wx.showToast({
        icon: 'none',
        title: '刷新间隔太短，请稍后重试',
        duration: 2500
      })
      return
    }
    this.data.refreshTime = Date.now()
    this.detach()
    this.init(this.data.room, "房间" + this.data.title)
  },

  init: function(room, title) {
    this.setData({
      room: room,
      title: "房间" + room,
      openid: app.globalData.openid
    })
    this.queryUser()
    this.queryGameInfo()
    this.getGameCardByUser()
    this.addMessageWatcher()
    // this.countdownAction()
  },

  detach: function() {
    if (watcher != null) watcher.close()
    if (countdownTimer != null) clearInterval(countdownTimer)
  },

  queryUser: function() {
    var that = this
    const db = wx.cloud.database()
    db.collection("user").where({
      _openid: app.globalData.openid
    })
    .get({
      success: function (res) {
        console.log('[云数据库] [user] 查询: ', res)
        var roleName = "侦探"
        if (res.data[0].role == "witness") {
          roleName = "目击者"
        } else if (res.data[0].role == "killer") { 
          roleName = "凶手"
        } else if (res.data[0].role == "abettor") { 
          roleName = "帮凶"
        }
        that.setData({
          role: res.data[0].role,
          solve: res.data[0].solve,
          hintText: "您当前的身份是：" + roleName,
          tempHintText: "您当前的身份是：" + roleName,
        })
      },
      fail: function (res) {
        console.log('[云数据库] [user] 查询失败: ', res)
      }
    })
  },

  addMessageWatcher: async function() {
    var that = this
    const db = wx.cloud.database()
    const _ = db.command
    watcher = db.collection("message").where({
      room: this.data.room,
      sendTimeTS: _.gt(Date.now()) 
    }).watch({
      onChange: snapshot => {
        console.log('[云数据库] [message] 新事件: ', snapshot)
        that.handleMessage(snapshot)
      },
      onError: err => {
        console.error('[云数据库] [message] 监听错误: ', err)
      }
    })
  },

  handleMessage: function(snapshot) {
    const messageArr = snapshot.docs
    if (messageArr.length <= 0) return
    const message = messageArr[messageArr.length - 1]
    console.log('[新消息] 接收: ', message)
    if (message.msgType == "command-change") {
      this.queryGameInfo()
    }
    if (message.msgType == "command-select") {
      this.queryGameScence()
    }
    if (message.msgType == "command-kill") {
      this.queryGameInfo()
      this.getGameCardByUser()
    }
    if (message.msgType == "command-solved") {
      var that = this
      wx.showModal({
        title: "破案成功",
        content: message.msgContent,
        showCancel: false,
        success: function(res) {
          if (that.data.resetCommand) {
            that.resetGame()
          } else {
            wx.reLaunch({
              url: '../startGame/startGame?room=' + that.data.room
            })
          }
        }
      })
    }
    if (message.msgType == "command-solved-fail") {
      this.querySolvedDetectiveNum(message.msgContent)
    }
    if (message.msgType == "command-reset") {
      this.setData({
        resetCommand: false
      })
    }
  },

  querySolvedDetectiveNum: async function(msgContent) {
    var that = this
    const db = wx.cloud.database()
    const userArr = await db.collection("user").where({
      role: "detective",
      solve: true
    }).get()
    const room = await db.collection("room").doc(this.data.room).get()
    if (userArr.data.length == room.data.detectiveNum) {
      wx.showModal({
        title: "破案失败",
        content: msgContent + "，当前所有侦探破案失败，凶手胜利",
        showCancel: false,
        success: function(res) {
          if (that.data.resetCommand) {
            that.resetGame()
          } else {
            wx.reLaunch({
              url: '../startGame/startGame?room=' + that.data.room
            })
          }
        }
      })
    } else {
      wx.showModal({
        title: "破案失败",
        content: msgContent,
        showCancel: false,
      })
    }
  },

  // 游戏重置，回到房间
  resetGame: function() {
    var that = this
    wx.showToast({
      title: '回房间中...',
    })
    wx.cloud.callFunction({
      name: 'resetGame',
      data: {
        room: this.data.room
      },
      success: function(res) {
        console.log('[云函数] [resetGame] 调用: ', res)
        that.sendMessage("command-reset")
        wx.hideLoading()
        wx.reLaunch({
          url: '../startGame/startGame?room=' + that.data.room
        })
      },
      fail: function(res) {
        console.log('[云函数] [resetGame] 调用失败: ', res)
        wx.hideLoading()
        wx.showToast({
          title: '设置失败，请重试',
          icon: 'none',
        })
      }
    })
  },

  sendMessage: function(command, msgContent) {
    const db = wx.cloud.database()
    db.collection("message").add({
      data: {
        room: this.data.room,
        sender: app.globalData.openid,
        msgType: command,
        msgContent: msgContent != null ? msgContent : "",
        nickname: app.globalData.userInfo.nickName,
        avatar: app.globalData.userInfo.avatarUrl,
        sendTime: new Date(),
        sendTimeTS: Date.now()
      },
      success: function (res) {
        console.log('[云数据库] [message] 插入: ', res)
      },
      fail: function (res) {
        console.log('[云数据库] [message] 插入失败: ', res)
      }
    })
  },
  
  queryGameScence: function() {
    var that = this
    wx.showLoading({
      title: '加载中...',
    })
    const db = wx.cloud.database()
    db.collection("game_scenes").where({
      room: this.data.room,
      processing: 0
    })
    .orderBy("serialNumber", "asc")
    .limit(6)
    .get({
      success: function (res) {
        console.log('[云数据库] [game_scenes] 查询: ', res)
        // 当前是否进行过换牌
        console.log('[changeCardTimes]: ', that.data.changeCardTimes)
        if (that.data.changeCardTimes <= 3) {
          that.queryGameScenceReplace(res.data)
        } else {
          wx.hideLoading()
          that.setData({
            scenesCardArray: res.data,
            tempScenesCardArray: copy(res.data)
          })
        }
      },
      fail: function (res) {
        console.log('[云数据库] [game_scenes] 查询失败: ', res)
        wx.hideLoading()
      }
    })
  },

  // 查询被替换的场景卡
  queryGameScenceReplace: function(array) {
    var that = this
    const db = wx.cloud.database()
    db.collection("game_scenes").where({
      room: this.data.room,
      processing: 1
    })
    .orderBy("serialNumber", "asc")
    .get({
      success: function (res) {
        console.log('[云数据库] [game_scenes] 查询 替换卡牌: ', res)
        wx.hideLoading()
        that.setData({
          scenesCardArray: array.concat(res.data),
          tempScenesCardArray: copy(array.concat(res.data)),
          operation: "none",
          hintText: that.data.tempHintText,
          buttonLeft: "换牌",
          buttonRight: "选择",
          changeCardIndex: -1
        })
      },
      fail: function (res) {
        console.log('[云数据库] [game_scenes] 查询替换卡牌失败: ', res)
        wx.hideLoading()
      }
    })
  },

  onLeftButtonTap: function() {
    if (this.data.changeCardTimes == 4) {
      wx.showToast({
        icon: 'none',
        title: '请先等待凶手完成卡片设置过程',
        duration: 3000,
      })
      return
    }
    if (this.data.operation == "none") {
      if (this.data.changeCardTimes == 0) {
        wx.showToast({
          icon: 'none',
          title: '换牌阶段已结束',
          duration: 3000
        })
        return
      }
      this.setData({
        operation: "changing",
        hintText: "请点击场景卡标题，选中要替换的蓝色场景卡，完成之后点击‘设置‘按钮进行替换操作",
        buttonLeft: "取消",
        buttonRight: "设置",
      })
    } else if (this.data.operation == "changing") {
      this.setData({
        operation: "none",
        hintText: this.data.tempHintText,
        buttonLeft: "换牌",
        buttonRight: "选择",
        changeCardIndex: -1
      })
    } else if (this.data.operation == "selecting") {
      this.setData({
        operation: "none",
        hintText: this.data.tempHintText,
        buttonLeft: "换牌",
        buttonRight: "选择",
        scenesCardArray: copy(this.data.tempScenesCardArray)
      })
    }
  },

  onRightButtonTap: async function() {
    if (this.data.changeCardTimes == 4) {
      wx.showToast({
        icon: 'none',
        title: '请先等待凶手完成卡片设置过程',
        duration: 3000,
      })
      return
    }
    if (this.data.operation == "none") {
      this.setData({
        operation: "selecting",
        hintText: "请点击场景卡放置选项，完成之后点击‘设置‘按钮确认",
        buttonLeft: "取消",
        buttonRight: "设置",
      })
    } else if (this.data.operation == "changing") {
      this.changeScenesCard()
    } else if (this.data.operation == "selecting") {
      this.selectScenesCard()
      this.setData({
        operation: "none",
        hintText: this.data.tempHintText,
        buttonLeft: "换牌",
        buttonRight: "选择",
        tempScenesCardArray: copy(this.data.scenesCardArray)
      })
    }
  },

  changeScenesCard: function() {
    const index = this.data.changeCardIndex
    if (index == -1) return
    const scenesCardArr = this.data.scenesCardArray
    this.updateScenesCard(
      scenesCardArr[index]._id, 
      scenesCardArr[index].selectedItem, 
      1,
      103 - this.data.changeCardTimes, // 103 是为了排序的时候，蓝色卡片在红色和黄色卡片之后，这里只要大于红色和黄色卡片总数即可
      "#888888"
    )
  },

  selectScenesCard: function() {
    const scenesCardArr = this.data.scenesCardArray
    const tempArr = this.data.tempScenesCardArray
    for (var i = 0; i < scenesCardArr.length; i++) {
      if (scenesCardArr[i].selectedItem != tempArr[i].selectedItem) {
        this.updateScenesCard(
          scenesCardArr[i]._id, 
          scenesCardArr[i].selectedItem,
          scenesCardArr[i].processing,
          scenesCardArr[i].serialNumber,
          scenesCardArr[i].cardColor
        )
      }
    }
  },

  updateScenesCard: function(id, selectedItem, processing, serialNumber, cardColor) {
    var that = this
    wx.showLoading({title: '设置中...'})
    wx.cloud.callFunction({
      name: 'updateGameScenes',
      data: {
        id: id,
        selectedItem: selectedItem,
        processing: processing,
        serialNumber: serialNumber,
        cardColor: cardColor
      },
      success: function(res) {
        console.log('[云函数] [updateGameScenes] 调用: ', res)
        wx.hideLoading()
        // 如果是换牌成功
        if (processing == 1) {
          that.saveGameInfo("command-change")
        } else { // 如果是设置卡牌选项
          that.sendMessage("command-select")
        }
      },
      fail: function(res) {
        console.log('[云函数] [updateGameScenes] 调用失败: ', res)
        wx.hideLoading()
        wx.showToast({
          title: '设置失败，请重试',
          icon: 'none',
        })
      }
    })
  },

  saveGameInfo: function(command) {
    // 换牌回合数减一，为0的时候换牌结束
    this.setData({
      changeCardTimes: this.data.changeCardTimes - 1
    })
    var that = this
    const db = wx.cloud.database()
    db.collection("game_info").add({
      data: {
        room: this.data.room,
        round: this.data.changeCardTimes,
        sendTime: new Date(),
        sendTimeTS: Date.now()
      },
      success: function (res) {
        console.log('[云数据库] [game_info] 插入: ', res)
        that.sendMessage(command)
      },
      fail: function (res) {
        console.log('[云数据库] [game_info] 插入失败: ', res)
      }
    })
  },

  queryGameInfo: function() {
    var that = this
    const db = wx.cloud.database()
    db.collection("game_info").where({
      room: this.data.room,
    })
    .orderBy("sendTimeTS", "desc")
    .limit(1)
    .get({
      success: function (res) {
        console.log('[云数据库] [game_info] 查询: ', res)
        that.setData({
          changeCardTimes: res.data.length == 0 ? 4 : res.data[0].round
        })
        that.queryGameScence()
      },
      fail: function (res) {
        console.log('[云数据库] [game_info] 查询失败: ', res)
      }
    })
  },

  radioChange: function(res) {
    var value = res.detail.value.split("-")
    this.data.scenesCardArray[value[0]].selectedItem = value[1]
  },

  onCardTitleTap: function(res) {
    const index = res.currentTarget.dataset.index
    if (index < 2) return
    this.setData({
      changeCardIndex: index
    })
  },

  queryAllUsers: async function() {
    const db = wx.cloud.database()
    const _ = db.command
    return (await db.collection("user").where({
      room: this.data.room,
      role: _.neq("witness")
    })
    .get()).data
  },

  queryGameCard: async function() {
    return (await wx.cloud.callFunction({
      name: "queryGameCard",
      data: {
        room: this.data.room,
        processing: true
      },
    })).result.data
  },

  getGameCardByUser: async function() {
    const userArr = await this.queryAllUsers()
    const gameCardArr = await this.queryGameCard()
    
    console.log('[云数据库] [user] 数据：', userArr)
    console.log('[云数据库] [game_card] 数据：', gameCardArr)

    var solveUserArr = []
    for (const item in userArr) {
      var user = userArr[item]
      var clueCardArr = []
      var trickCardArr = []
      for (const card in gameCardArr) {
        var gameCard = gameCardArr[card]
        if (user._openid == gameCard.openid) {
          if (gameCard.cardType == "clue") {
            clueCardArr.push(gameCard)
          }
          if (gameCard.cardType == "trick") {
            trickCardArr.push(gameCard)
          }
        }
      }
      user.clueCardArray = clueCardArr
      user.trickCardArray = trickCardArr
      if (user._openid != this.data.openid) {
        solveUserArr.push(user)
      }
    }
    this.setData({
      userArray: userArr,
      solveUserArray: solveUserArr
    })
    console.log('[云数据库] [user] [game_card] 合成数据：', this.data.userArray)
  },

  onKillerButtonTap: function() {
    if (this.data.changeCardTimes != 4) {
      wx.showToast({
        icon: 'none',
        title: '您已设置过线索卡和手段卡',
        duration: 3000
      })
      return
    }
    this.setData({
      showSheet: true
    })
  }, 

  onSheetCancel: function() {
    this.setData({
      showSheet: false
    })
  },

  onSheetConfirm: async function() {
    wx.showLoading({
      title: '提交中...',
    })
    const trickResult = await wx.cloud.callFunction({
      name: "updateGameCard",
      data: {
        id: this.data.trickCardId
      }
    })
    const clueResult = await wx.cloud.callFunction({
      name: "updateGameCard",
      data: {
        id: this.data.clueCardId
      }
    })
    wx.hideLoading()
    if (trickResult.result.stats.updated == 1 && clueResult.result.stats.updated == 1 ) {
      this.setData({
        showSheet: false
      })
      this.saveGameInfo("command-kill")
    } else {
      wx.showToast({
        title: '提交失败',
      })
    }
  },
  
  trickRadioChange: function(res) {
    this.setData({
      trickCardId: res.detail.value
    })
  },
  
  clueRadioChange: function(res) {
    this.setData({
      clueCardId: res.detail.value
    })
  },

  countdownAction: function() {
    var that = this;
    countdownTimer = setInterval(function() {
      that.data.countdown--
      if (that.data.countdown < 0) {
          clearInterval(countdownTimer)
      } else {
        that.setData({
          countdown: that.data.countdown
        })
      }
    }, 1000)
  },

  onSolveButtonTap: function() {
    if (this.data.solve) {
      wx.showToast({
        icon: 'none',
        title: '您已破案',
        duration: 3000
      })
      return
    }
    this.setData({
      showSolveSheet: true
    })
  }, 

  onSolveSheetCancel: function() {
    this.setData({
      showSolveSheet: false
    })
  },

  onSolveSheetConfirm: async function() {
    const userArr = this.data.userArray
    var section = 0
    for (const item in userArr) {
      const trickCardArr = userArr[item].trickCardArray
      for (const trick in trickCardArr) {
        console.log("====>>>> selected 11 : ", trickCardArr[trick].selected)
        console.log("====>>>> selected 22 : ", trickCardArr[trick]._id)
        console.log("====>>>> selected 33 : ", this.data.trickCardId)
        if (trickCardArr[trick].selected && trickCardArr[trick]._id == this.data.trickCardId) {
          section++;
        }
      }
      const clueCardArr = userArr[item].clueCardArray
      for (const clue in clueCardArr) {
        console.log("====>>>> selected 44 : ", clueCardArr[clue].selected)
        console.log("====>>>> selected 55 : ", clueCardArr[clue]._id)
        console.log("====>>>> selected 66 : ", this.data.clueCardId)
        if (clueCardArr[clue].selected && clueCardArr[clue]._id == this.data.clueCardId) {
          section++;
        }
      }
    }
    if (section >= 2) { // 破案成功
      this.sendMessage("command-solved", "恭喜" + app.globalData.userInfo.nickName + "成为最佳侦探")
    } else {
      this.sendMessage("command-solved-fail", app.globalData.userInfo.nickName + "破案失败")
      this.changeUserStatus()
    }
    this.setData({
      showSolveSheet: false,
      solve: true,
    })
  },

  changeUserStatus: async function() {
    wx.showLoading({
      title: '提交中...',
    })
    wx.cloud.callFunction({
      name: "modifyUser",
      data: {
        status: "gaming",
        room: this.data.room,
        solve: true,
      },
      success: function (res) {
        console.log('[云函数] [modifyUser] 调用: ', res)
        wx.hideLoading()
      },
      fail: function (res) {
        console.log('[云函数] [modifyUser] 调用失败: ', res)
        wx.hideLoading()
      }
    })
  },
  
  onTrickSolveTap: function(res) {
    var id = res.currentTarget.dataset.id
    console.log('onTrickSolveTap ', id)
    const solveUserArr = this.data.solveUserArray
    for (const item in solveUserArr) {
      const trickCardArr = solveUserArr[item].trickCardArray
      for (const trick in trickCardArr) {
        trickCardArr[trick].mark = (trickCardArr[trick]._id == id)
      }
    }
    this.setData({
      trickCardId: id,
      solveUserArray: this.data.solveUserArray
    })
  },
  
  onClueSolveTap: function(res) {
    var id = res.currentTarget.dataset.id
    console.log('onClueSolveTap ', id)
    const solveUserArr = this.data.solveUserArray
    for (const item in solveUserArr) {
      const clueCardArr = solveUserArr[item].clueCardArray
      for (const clue in clueCardArr) {
        clueCardArr[clue].mark = (clueCardArr[clue]._id == id)
      }
    }
    this.setData({
      clueCardId: id,
      solveUserArray: this.data.solveUserArray
    })
  }
})

function copy(array) {
  return JSON.parse(JSON.stringify(array))
}